<template>
  <div ref="modal" class="modal-column">
    <div class="amount-calculator-container">
      <div class="demo-content">计算 [例如：5.99+(10-8.8)*5]</div>
      <div class="calcu-text-container">
                <textarea ref="originEquation" v-model="equationVal" @input="onEquationChange" @keydown="onKeyDown"
                          style="height: 125px;"></textarea>
      </div>
      <div class="result-container">
        <div class="action-tip">亲，按回车键可以快速保存计算结果哦！</div>
        <div class="result-content">
          <span class="result-text-content">计算结果：</span>
          <span id="calcuValue" class="result-num-content">{{ resultData }}</span>
        </div>
      </div>
    </div>
    <div class="modal-column-between">
      <vxe-button icon="fa fa-close" @click="emits('close')">取消</vxe-button>
      <vxe-button status="primary" icon="fa fa-check" @click="submit()">确定</vxe-button>
    </div>
  </div>
</template>

<script setup>
import {defineProps, nextTick, onMounted, ref} from "vue";
import {message} from "heyui.ext";

const emits = defineEmits(['success', 'close']);

const props = defineProps({
  originData: String
});

const equationVal = ref('0.00')
const resultData = ref('0.00')
const originEquation = ref(null)

/**
 * <p>****************************************************************************</p>
 * <p><b>Copyright © 2010-2022杭州财汇餐谋科技有限公司All Rights Reserved<b></p>
 * <ul style="margin:15px;">
 * <li>Description : </li>
 * <li>Version     : 1.0</li>
 * <li>Creation    : 2022年10月23日</li>
 * <li>@author     : ____′↘夏悸</li>
 * </ul>
 * <p>****************************************************************************</p>
 */
const onEquationChange = (e) => {
  let arrayData = sliceCountStr(e.target.value);
  let resultNumber = countHandle(arrayData);
  try {
    resultNumber = eval(e.target.value);
    if (!isNaN(resultNumber)) {
      if (String(resultNumber).indexOf('.') !== -1) {
        resultNumber = parseFloat(resultNumber.toPrecision(30)).toFixed(2);
        var x = String(resultNumber).indexOf('.') + 1;   //小数点的位置
        var y = String(resultNumber).length - x;  //小数的位数
        if (y === 0) {
          resultNumber = resultNumber + '.00';
        } else if (y === 1) {
          resultNumber = resultNumber + '0';
        }
      } else {
        resultNumber = resultNumber + '.00';
      }
      resultData.value = resultNumber;
    } else resultData.value = '0.00';
  } catch (e) {
    resultData.value = '0.00';
  }
}

const onKeyDown = (e) => {
  if (e.keyCode === 13 || e.keyCode === 9) {
    submit();
  }
}

// str 即为input输入的数据
const sliceCountStr = (str) => {
  let arr = []; // 记录分割计算表达式
  for (let i = 0; i < str.length; i++) {
    let item = str.charAt(i);
    let num = item;
    if (/[\d|\.]/.test(item)) {
      let j = i + 1;
      for (; j < str.length - 1; j++) {
        let otherItem = str.charAt(j);
        if (!/[\d|\.]/.test(otherItem)) {
          break;
        }
      }
      num = str.slice(i, j);
      i = j - 1;
      num = +num;
    }
    arr.push(num);
  }
  return arr;
}

// arr 即为上一步处理好的数组
const countHandle = (arr) => {
  let charArr = [],
      numArr = [];
  for (let i = 0; i < arr.length; i++) {
    if (typeof arr[i] == 'number') {
      numArr.push(arr[i]);
    } else {
      if (charArr.length) {
        // 步骤1
        // 如果当前的运算符的优先级比栈顶的优先级低或相等，就说明需要把前面的值全部计算好
        // 存储运算符的栈要一直出栈，直到栈为空或当前的字符的优先级比栈顶的优先级高
        while (isPop(arr[i], charArr[charArr.length - 1])) {
          let t2 = numArr.pop();
          let t1 = numArr.pop();
          let char = charArr.pop();
          handleCalculation(numArr, t1, t2, char);
        }
        // 当前运算符为右括号
        if (arr[i] === ')' || arr[i] === '）') {
          // 取栈顶运算符
          let st = charArr[charArr.length - 1];
          // 步骤2
          // 遇到右括号也要一直出栈，直到遇到左括号
          while (st !== '(' && st !== '（') {
            let t1, t2;
            let char = charArr.pop();
            if (char !== '(' && char !== '（') {
              t2 = numArr.pop();
              t1 = numArr.pop();
              handleCalculation(numArr, t1, t2, char);
            }
            st = char;
          }
        }
        // 运算符不为右括号
        if (arr[i] !== ')' && arr[i] !== '）') {
          charArr.push(arr[i]);
        }
      } else {
        // 步骤3
        // 运算符栈为空，直接入栈
        charArr.push(arr[i]);
      }
    }
  }
  // 步骤4
  // 最后运算符栈如果还有字符，要一直出栈直到为空
  while (charArr.length) {
    let t2 = numArr.pop();
    let t1 = numArr.pop();
    let char = charArr.pop();
    handleCalculation(numArr, t1, t2, char);
  }
  return numArr[0];
}

// 基本加减乘除运算处理
const handleCalculation = (numArr, num1, num2, char) => {
  if (char === '+') {
    numArr.push(num1 + num2);
  } else if (char === '-') {
    numArr.push(num1 - num2);
  } else if (char === '*') {
    numArr.push(num1 * num2);
  } else if (char === '/') {
    numArr.push(num1 / num2);
  }
}

// 判断运算符的优先级，是否出栈进行计算
const isPop = (char1, char2) => {
  // 运算符栈为空
  if (!char2) {
    return false;
  }
  // 运算符优先级相同
  if ((char1 === '+' || char1 === '-') && (char2 === '+' || char2 === '-')) {
    return true;
  }
  // 前者运算符优先级比后者低
  if ((char1 === '+' || char1 === '-') && (char2 === '*' || char2 === '/')) {
    return true;
  }
  // 运算符优先级相同
  if ((char1 === '*' || char1 === '/') && (char2 === '*' || char2 === '/')) {
    return true;
  }
  // 前者运算符优先级比后者高
  if ((char1 === '*' || char1 === '/') && (char2 === '+' || char2 === '-')) {
    return false;
  }
}

const submit = () => {
  if (resultData.value > 999999999.99) {
    message.error('计算结果超过范围');
  } else {
    emits('success', resultData.value);
  }
}

onMounted(() => {
  setTimeout(() => {
    nextTick(() => {
      originEquation.value.focus();
    })
  }, 100);

  if (props.originData && props.originData !== '') {
    try {
      if (isNaN(eval(props.originData))) {
        equationVal.value = props.originData;
        resultData.value = props.originData;
      }
    } catch (e) {
      equationVal.value = props.originData;
    }
  }
})

</script>

<style lang="less" scoped>
.amount-calculator-container {
  flex: 1;
  padding: 25px 0 0;
}

.demo-content {
  color: #333333;
  font-size: 13px;
  line-height: 18px;
  padding: 0 20px;
}

.calcu-text-container {
  margin: 10px 0;
  padding: 0 20px;
}

.calcu-text-container textarea {
  resize: none;
  outline: none;
  border: 1px solid #dadada;
  color: #333333;
  font-size: 22px;
  line-height: 30px;
  padding: 14px;
  width: 100%;
  height: 109px;
  box-sizing: border-box;
  font-weight: bold;
}

.result-container {
  height: 62px;
  padding: 0 20px;
}

.action-tip {
  float: left;
  margin-top: 8px;
  color: #FD7400;
  font-size: 13px;
  line-height: 18px;
}

.result-content {
  float: right;
  max-width: 520px !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  white-space: normal !important;
}

.result-text-content {
  float: left;
  color: #333333;
  font-size: 13px;
  line-height: 18px;
  margin-top: 10px;
}

.result-num-content {
  float: right;
  color: #2080f0;
  line-height: 33px;
  font-size: 26px;
  margin-top: 0;
  font-weight: bold;
  max-width: 434px;
  overflow: hidden;
  white-space: nowrap;
  display: inline-block;
}
</style>
